/*
** A Driver for a variety of GP classification algorithms
*/

/* TODO
	- do mpi enabled cross validation 
*/

// third party includes
#include <mpi.h>
#include <string>
#include <map>
#include <set>
#include <sstream>
#include <fstream>
#include <iomanip>
#include <strings.h>

// local includes
#include <crf_sequence/crf_learn.h>
#include <crf_sequence/param.h>
#include <crf_sequence/sparse_array.h>
#include <crf_sequence/util.h>
#include <crf_sequence/data.h>
#include "st_cmdline.h"
#include "st_classifier.h"

#include "detect_cliques.h"
#include "cmdline.h"

static const char *REVISION = "$Revision: 1.10 $";

int main(int argc, char **argv)
{
	MPI_Init(&argc,&argv);
	int rank, size;
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Comm_size(MPI_COMM_WORLD, &size);

	if (rank == 0)
	{
		std::cout << "Super-tagging CRF algorithms: Copyright 2006 Phil Blunsom\n";
		std::cout << REVISION << '\n' << std::endl;
	}
	// this parameter stores global config info
	GPParameter *param = new GPParameter;

	// process command line args
	char *vector_events_file=0;
	float gaussian_prior=1.0;
	std::string param_file="", param_out_file="";

	// process cmdline
	gengetopt_args_info args_info;
	if (cmdline_parser (argc, argv, &args_info) != 0)
		return EXIT_FAILURE;
	if (cmdline_parser_configfile(args_info.st_file_arg, &args_info, 1, 0, 1) != 0)
		return EXIT_FAILURE;

	if(args_info.model_given)		   param_file = args_info.model_arg;
	param->lbfgs_vecs = args_info.lbfgs_memory_arg;
	gaussian_prior = args_info.gaussian_prior_arg;
	param->max_its = args_info.iter_arg;
	param->eps = args_info.precision_arg;
	param->debug = args_info.verbose_given;

	if(args_info.vector_events_given)  
		vector_events_file = args_info.vector_events_arg;
	else
	{
		std::cout << "Please supply event files with the --vector_events option\n";
		return EXIT_FAILURE;
	}
	if(args_info.model_out_given)	   
		param_out_file = args_info.model_out_arg;
	else
	{
		std::cout << "Please supply a file in which to save the model weights";
		std::cout << " with the --model_out option\n";
		return EXIT_FAILURE;
	}

	// initialise parameter
	param->sigma_sqr = gaussian_prior;

	// run the algorithm
	if (rank==0) 
		std::cout << "Root process using Parameter:\n" << *param << "\n\n";

	if (args_info.crf_given)
	{
		FlatEventsPtr data(new FlatEvents());
		data->read(vector_events_file);
		param->basis = param->m = data->events(); //!!!
		param->n = data->features();
		crf_learn(param, data, param_file, param_out_file);
	}
	else
	{
		FlatEventsPtr data(new FlatEvents());
		data->read(vector_events_file);
		param->basis = param->m = data->events(); //!!!
		param->n = data->features();
		flat_learn(param, data, param_file, param_out_file);
	}

	delete param;

	MPI_Finalize();
	return 0;
}
